package com.greensoftcodeplus.redislog.component;


import com.greensoftcodeplus.redislog.properties.MyRedisPropertiesLog;
import com.greensoftcodeplus.redislog.utils.ResolvingFun;
import lombok.extern.slf4j.Slf4j;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.context.ApplicationContext;

import java.lang.reflect.Method;

/**
 * 使用自定义代理完成日志输出
 */
@Slf4j
public class RedisAdvice extends ResolvingFun {


    ApplicationContext applicationContext;

    public RedisAdvice(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    public Object interceptorRedisFactory(MethodInvocation invocation) throws Throwable {
//        if (!log.isDebugEnabled())
//            return invocation.proceed();

        Object ret = invocation.proceed();
        String methodName = invocation.getMethod().getName();
//        if (methodName.equals("isPipelined") || methodName.equals("close"))
//            return invocation.proceed();
        //获得LettuceConnectionFactory类  RedisConnection getConnection() 方法，其实就是给  RedisConnection函数利用代理ProxyUtils增强
        if (methodName.equals("getConnection")) {
            return ProxyUtils.getProxy(ret, this::interceptorRedis);
        }
        return ret;
    }

    public Object interceptorRedis(MethodInvocation invocation) throws Throwable {
        Method method = invocation.getMethod();
        String methodName  = method.getName();
        if (methodName .equals("isPipelined") || methodName .equals("close") ||  methodName.equals("isQueueing")) {
            return invocation.proceed();
        }

        LogDto logDto = new LogDto();
        logDto.setMethod(methodName );

        Object target = invocation.getThis();
        logDto.setClas(target.getClass().getName());

        Object[] args = invocation.getArguments();
        String argsStr= ResolvingFun.ResolvingArgs(methodName,args);
        // String s = JSONObject.toJSONString(object);
         logDto.setPara(argsStr);
//        logDto.setPara(s);
        Object ret = null;
        long start = System.currentTimeMillis();
        try {
            ret = invocation.proceed();
            return ret;
        } catch (Exception exp) {
            logDto.setExp(exp);
            throw exp;
        } finally {
            logDto.setCostTime(System.currentTimeMillis() - start);
            logDto.setResult(ret);
//            doLogx(logDto);
            MyRedisPropertiesLog myRedisPropertiesLog = applicationContext.getBean(MyRedisPropertiesLog.class);
            printLogx(logDto,myRedisPropertiesLog );
        }
    }
}
